
/*
 * This filter takes two input streams and compares each ones' data against the other
 * to determine of any normalization occurred previously. If Wild Points were detected
 * IE: dirty and clean data did not match, then Wild Point are written to the specified
 * Wild Point file and clean data is written to the specified clean file (if specified)
 * @author Team 10
 * 
 */
import java.io.FileWriter;
import java.io.IOException;

public class SuperSinkFilter extends FilterFramework2
{
	
	private int[] typesToFilterClean;
	private int[] typesToFilterDirty;
	private String filename;
	private String wildPointFilename;
	private int asteriskFlagId;
	
	/*
	 * This constructor takes 5 configuration inputs
	 * 1) An array of ints indicating the order data is to be printed in the clean file
	 * 		- IDs not included in the array will be ommited in the final output
	 * 2) An array of ints indicating the order data is to be printed in the dirty (Wild Point) file
	 * 3) String Clean filename (Can be null)
	 * 4) String Dirty (Wild Point) filename (Must be specified)
	 * 5) An integer indicating which Data ID is to have the Asterisk indicator in the clean output
	 */
	public SuperSinkFilter(int[] typesToFilterClean_, int[] typesToFilterDirty_, String filename_, String wildPointFilename_, int asteriskFlagId_)
	{
		// this filter should have 2 piped inputs and 0 piped outputs
		super(2,0);
		typesToFilterDirty = typesToFilterDirty_;
		typesToFilterClean = typesToFilterClean_;
		filename=filename_;
		wildPointFilename = wildPointFilename_;
		asteriskFlagId = asteriskFlagId_;
	}
	
	/*
	 * This filter will compare raw data from the Source filter (pipe 0) with extrapolated
	 * cleaned data from the previous filter (pipe 1) and will mark discrepancies as 
	 * Wild Point data, sorting them into files and marking asterisks accordingly. 
	 */
	public void run()
    {
		int bytesread = 0;				// This is the number of bytes read from the stream
		
		/*************************************************************
		*	First we announce to the world that we are alive...
		**************************************************************/
		System.out.print( "\n" + this.getName() + "::Sink Reading ");

		// These FileWriters reference the output files respectively
		FileWriter normalFileOut = null;
		FileWriter wildFileOut = null;
		
		// We create the individual file headers
		String dirtyFileHeader = dataHeader(typesToFilterDirty);
		String cleanFileHeader = dataHeader(typesToFilterClean);
		
		// These Measurement objects are used to easily extract individual pieces
		// of data from the data frames. Each input gets its own Measurement Object
		Measurement cleanMeasurement = new Measurement();
		Measurement dirtyMeasurement = new Measurement();
		
		try 
		{
			// if the clean file has been specified
			if(filename != null)
			{
				// we initialize its File Writer
				normalFileOut = new FileWriter(filename);
				normalFileOut.write(cleanFileHeader);
			}
			
			// We initialize the Wild Point File Writer 
			wildFileOut = new FileWriter(wildPointFilename);
			wildFileOut.write(dirtyFileHeader);
		}
		catch(IOException e)
		{
			// Print the error
			System.out.print( "\n" + this.getName() + "File ::Sink Exiting; bytes read: " + bytesread );		
		}
		
		while (true)
		{
			try
			{
				// Attempt to read the two Byte Streams
				cleanMeasurement.readByteStream(this, 0);
				dirtyMeasurement.readByteStream(this, 1);
				
				// If the data from the two streams match we know no Wild Point conversion
				// took place. If the two data objects do not match we know that frame has
				// an extrapolated Wild Point value
				if(!cleanMeasurement.equals(dirtyMeasurement))
				{
					// we write the dirty value out to the Wild Point file
				    wildFileOut.write(dirtyMeasurement.toString(typesToFilterDirty));
				    
				    wildFileOut.flush();
				}
				
				// If a clean file has been specified
				if(normalFileOut != null)
				{
					// If the two frames (clean and dirty) match, then no Wild Point exists
					if(cleanMeasurement.equals(dirtyMeasurement))
					{
						// we write the data normally
						normalFileOut.write(cleanMeasurement.toString(typesToFilterClean));
					}
					else // the two frames do not match, a wild point DOES exist
					{
						// we write the data to the clean Filter WITH an asterisk (if specified)
						normalFileOut.write(cleanMeasurement.toString(typesToFilterClean, asteriskFlagId));
					}
					normalFileOut.flush();
				}
			}
			catch (EndOfStreamException e)
			{
				System.out.print( "\n" + this.getName() + "::Sink 1 Exiting; bytes read: " + bytesread );
				break;

			} // catch
			catch (IOException e)
			{
				System.out.print( "\n" + this.getName() + "::Sink 2 Exiting; bytes read: " + bytesread );
				break;

			} // catch
			catch (ClassNotFoundException e)
			{
				System.out.print( "\n" + this.getName() + "::Sink 3 Exiting; bytes read: " + bytesread );
				break;

			} 
		}
	}
	
	// This function streamlines the header printing functionality
	// It returns a string based on the types of data to be filtered (derived from
	// the class constructor parameters)
	public String dataHeader(int[] typestofilter)
	{
		// initialize the return value
		String header = "";
		
		// We check each element in the to filter array of IDs
		for(int i=0; i < typestofilter.length ; i++)
		{
			// Switch on the ID value to print the correct header
			switch(typestofilter[i]) 
			{
				case 0:
					header = header.concat("      TIME      ");
					break;
				case 1:
					header = header.concat("         VELOCITY   ");
					break;
				case 2:
					header = header.concat("       ALTITUDE   ");
					break;
				case 3:
					header = header.concat("       PRESSURE   ");
					break;
				case 4:
					header = header.concat("       TEMPERATURE  ");
					break;
				case 5:
					header = header.concat("      ATTITUDE   ");
					break;
			}
		}
		
		// return the final string
		return header.concat("\r\n");
	}
	
}